package com.cloud.api.filter;

import com.alibaba.fastjson.JSONObject;
import com.cloud.api.response.User;
import com.cloud.base.CacheConstant;
import com.cloud.base.bean.CloudResponse;
import com.cloud.base.cache.CloudRedisTemplate;
import com.cloud.base.util.DateUtil;
import com.cloud.base.util.General;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

@Component
public class RequestSignFilter implements GlobalFilter, Ordered {

    @Autowired
    private CloudRedisTemplate cloudRedisTemplate;

    @Value("${app.appSecret}")
    private String appSecret;
    //任务接口
    private final List uris = Arrays.asList("/app/game/date/list", "/app/game/many/list", "/app/game/generic/list");
    //登录接口
    private final String loginUrl = "/app/personal/buyer/login";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();

        //请求地址uri
        String urlPath = request.getURI().getPath();

        //过滤1.登录时判断是否开挂
        if(urlPath.equals(loginUrl)){
            //标记该IP是否开挂
            String times = request.getHeaders().getFirst("times");
            if(times == null || !Integer.valueOf(times).equals(Integer.valueOf(DateUtil.getDay()))){
                String ip = getIpAddress(request);
                cloudRedisTemplate.set(CacheConstant.GUA_IP + ip, 1, -1);
            }
        }

        //过滤2.请求任务列表做限制
        if (!uris.contains(urlPath)) {
            //非验证组里的uri直接请求
            return chain.filter(exchange);
        }

        //限制请求频次
        boolean isPass = limitUserRequestUrl(request);

        if (isPass && sign(request.getHeaders().getFirst("sign"), request.getHeaders().getFirst("timestamp"))){
            return chain.filter(exchange);
        }

        ServerHttpResponse response = exchange.getResponse();
//        byte[] bytes = JSONObject.toJSONBytes(new CloudResponse(REQUEST_SUCCESS, null));
        byte[] bytes = JSONObject.toJSONBytes(new CloudResponse(new ArrayList<>()));
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        response.getHeaders().setContentType(MediaType.valueOf("application/json;charset=UTF-8"));
        return response.writeWith(Flux.just(buffer));

    }

    private boolean sign(String sign, String timestamp) {
        if(StringUtils.isBlank(sign) || StringUtils.isBlank(timestamp)) {
            return false;
        }
        long diff = System.currentTimeMillis() - Long.valueOf(timestamp);
        String signMd5 = General.md5(timestamp.concat(appSecret));
        if (!sign.equals(signMd5) || diff > 10000){
            return false;
        }
        return true;
    }

    private boolean limitUserRequestUrl(ServerHttpRequest request){

        String ip = getIpAddress(request);
        if("0.0.0.0".equals(ip)){
            return false;
        }
//        System.out.println("============方法外获取的IP================" + ip);
        String ipCount = cloudRedisTemplate.get(CacheConstant.USER_IP + ip, String.class);
        if (!StringUtils.isBlank(ipCount)){
            //请求已存在，表示频次过高
            return false;
        }

        Random rand = new Random();
        int secondTime;
        //如果该IP是挂，延长缓存时间
        String guaCount = cloudRedisTemplate.get(CacheConstant.GUA_IP, String.class);
        if (!StringUtils.isBlank(guaCount)){
            secondTime = rand.nextInt(301) + 60;
        }else{
            secondTime = rand.nextInt(6) + 10;
        }

        cloudRedisTemplate.set(CacheConstant.USER_IP + ip, 1, secondTime);
        return true;
    }

    public int getOrder() {
        return -2;
    }


    public static String getIpAddress(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();
        String ip = headers.getFirst("x forwarded for");
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if (ip.indexOf(",") !=  1) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("Proxy Client IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("WL Proxy Client IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("X Real IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddress().getAddress().getHostAddress();
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = "0.0.0.0";
        }
        return ip;
    }

}
